/* 
  OfflineStorage - Database:
  - provides init() method to setUp the database instance for the client
  - provides getter and setter methods to store and retrieve business objects in the database (internally converted into select and insert sql statements)
*/

/**
 * Constructor
 * @param {function} callback
 */
function Database(callback){
    this.request;
    this.request = indexedDB.open("wm2014", 1);
    this.request.onerror = this.errorInit;
    this.request.onupgradeneeded = function(event){
        var db = event.target.result;
        
        objectStore = db.createObjectStore("groups", { keyPath: "id"} );
        objectStore = db.createObjectStore("matches", { keyPath: "id"});
        objectStore = db.createObjectStore("goals", { keyPath: "id"} );
        objectStore = db.createObjectStore("teams", { keyPath: "id"} );
    }
    this.request.onsuccess = function(){
        callback();
    }
}

/**
 * Notify SoapRequestErrorHandler about a DB-init-error.
 * @param {type} event
 */
Database.prototype.errorInit = function(event){
    var soapRequestErrorHandler = new SoapRequestErrorHandler();
    soapRequestErrorHandler.error("The database could not be initialised!");
}

/**
 * Notify SoapRequestErrorHandler about a DML-error.
 * @param {type} event
 */
Database.prototype.error = function(event){
    var soapRequestErrorHandler = new SoapRequestErrorHandler();
    soapRequestErrorHandler.error("The database could not be accessed!");
}

/**
 * Saves a Matchobject to the IndexedDB
 * @param {Match} matchObject
 */
Database.prototype.setMatch = function(matchObject){
    var	transaction = this.request.result.transaction(["matches"], "readwrite");
    var	objectStore = transaction.objectStore("matches");
    var matchObj = matchObject.getDatabaseObject();
    var request = objectStore.openCursor(matchObj.id);
    var selfObj = this;

    request.onsuccess = function(e) {
      var cursor = e.target.result;
      if (cursor) { // key already exist
         cursor.update(matchObj);
      } else { // key not exist
         objectStore.add(matchObj);
      }
      var goalsOfMatch = matchObject.getGoals();
      for(key in goalsOfMatch){
          var goal = goalsOfMatch[key];
          goal.setMatchId(matchObject.getId());
          selfObj.setGoal(goal);
      }
    };
    request.onerror = this.error;
}

/**
 * Calls the callbackfunction with a Matchobject as the first param
 * @param {int} id
 * @param {function} callback
 */
Database.prototype.getMatchById = function(id, callback){
    var	transaction = this.request.result.transaction(["matches"], "readwrite");
    var	objectStore = transaction.objectStore("matches");
    var request = objectStore.get(id);
    var dbObject = this;

    request.onsuccess = function(){
        var match = new Match();
        match.convertToBusinessObject(request.result);        
        dbObject.getGoalsByMatchId(match.getId(), function(arrGoals){
            for(var key in arrGoals){
                match.addGoal(arrGoals[key]);
            }
            callback(match);
        });
    };
    request.onerror = this.error;
}

/**
 * Saves a Goal object to the indexedDB
 * @param {Goal} goalObject
 */
Database.prototype.setGoal = function(goalObject){
    var	transaction = this.request.result.transaction(["goals"], "readwrite");
    var	objectStore = transaction.objectStore("goals");
    var gObj = goalObject.getDatabaseObject();
    var request = objectStore.openCursor(gObj.id);

    request.onsuccess = function(e) {
      var cursor = e.target.result;
      if (cursor) { // key already exist
         cursor.update(gObj);
      } else { // key not exist
         objectStore.add(gObj);
      }
    };
    request.onerror = this.error;
}

/**
 * * Calls the callbackfunction with a array of Goal-objects as the first param
 * @param {type} matchId
 * @param {type} callback
 */
Database.prototype.getGoalsByMatchId = function(matchId, callback){
    var	transaction = this.request.result.transaction(["goals"], "readwrite");
    var	objectStore = transaction.objectStore("goals");
    var request = objectStore.openCursor();

    var arrGoals = new Array();
    request.onsuccess = function(e){
        var cursor = e.target.result;
         if (cursor) {
             if(cursor.value.matchId == matchId){
                 var goal = new Goal();
                 goal.convertToBusinessObject(cursor.value);
                 arrGoals.push(goal);
             }
             cursor.continue(); 
         }else{
             callback(arrGoals);
         }
    };
    request.onerror = this.error;
}

Database.prototype.setGroup = function(groupObject){
    var	transaction = this.request.result.transaction(["groups"], "readwrite");
    var	objectStore = transaction.objectStore("groups");
    var gObj = groupObject.getDatabaseObject();
    var request = objectStore.openCursor(gObj.id);
    selfObj = this;

    request.onsuccess = function(e) {
      var cursor = e.target.result;
      if (cursor) { // key already exist
         cursor.update(gObj);
      } else { // key not exist
         objectStore.add(gObj);
      }

      var matchesOfGroup = groupObject.getAllMatches();
      for(key in matchesOfGroup){
          var match = matchesOfGroup[key];
          match.setGroupId(groupObject.getGroupId());
          selfObj.setMatch(match);
      }

      var teamsOfGroup = groupObject.getAllTeams();
      for(index in teamsOfGroup) {
          var team = teamsOfGroup[index];
          team.setGroupId(groupObject.getGroupId());
          selfObj.setTeam(team);
      }
    };
    request.onerror = this.error;
}

Database.prototype.getAllGroups = function(callback){
    var	transaction = this.request.result.transaction(["groups"], "readwrite");
    var	objectStore = transaction.objectStore("groups");
    var request = objectStore.openCursor();

    var arrGroups = new Array();
    var dbObj = this;
    request.onsuccess = function(e){
        var cursor = e.target.result;
        if (cursor) { // key already exist
            var group = new Group();
            group.convertToBusinessObject(cursor.value);
            arrGroups.push(group);
            cursor.continue();
        } else { // key not exist
            callback(arrGroups);
        }
    };
    request.onerror = this.error;
}

Database.prototype.getMatchesByGroupId = function(groupId, callback){
    var	transaction = this.request.result.transaction(["matches"], "readwrite");
    var	objectStore = transaction.objectStore("matches");
    var request = objectStore.openCursor();

    var arrMatches = [];
    request.onsuccess = function(e){
        var cursor = e.target.result;
         if (cursor) {
             if(cursor.value.groupId == groupId){
                 var match = new Match();
                 match.convertToBusinessObject(cursor.value);
                 arrMatches.push(match);
             }
             cursor.continue(); 
         }else{
             callback(arrMatches);
         }
    };
    request.onerror = this.error;
}

Database.prototype.getTeamsByGroupId = function(groupId, callback){
    var	transaction = this.request.result.transaction(["teams"], "readwrite");
    var	objectStore = transaction.objectStore("teams");
    var request = objectStore.openCursor();

    var arrTeams = [];
    request.onsuccess = function(e){
        var cursor = e.target.result;
        if (cursor) {
            if(cursor.value.groupId == groupId){
                var team = new Team();
                team.convertToBusinessObject(cursor.value);
                arrTeams.push(team);
            }
            cursor.continue();
        }else{
            callback(arrTeams);
        }
    };
    request.onerror = this.error;
}

Database.prototype.getGroupById = function(id, callback){
    var	transaction = this.request.result.transaction(["groups"], "readwrite");
    var	objectStore = transaction.objectStore("groups");
    var request = objectStore.get(id);
    request.onerror = this.error;
    var dbObject = this;

    request.onsuccess = function(){
        var group = new Group();
        group.convertToBusinessObject(request.result);

        dbObject.getMatchesByGroupId(group.getGroupId(), function(arrMatches){
            for(var key in arrMatches){
                group.addMatch(arrMatches[key]);
            }
        });

        dbObject.getTeamsByGroupId(group.getGroupId(), function(arrTeams){
            for(var key in arrTeams){
                group.addTeam(arrTeams[key]);
            }
        });

        callback(group);
    };
    request.onerror = this.error;
}

/**
 * Saves an object team to the indexedDB.
 * @param {Team} teamObject
 */
Database.prototype.setTeam = function(teamObject){
    var	transaction = this.request.result.transaction(["teams"], "readwrite");
    var	objectStore = transaction.objectStore("teams");
    var tObj = teamObject.getDatabaseObject();
    var request = objectStore.openCursor(tObj.id);
    request.onsuccess = function(e) {
        var cursor = e.target.result;
        if (cursor) { // key already exist
            cursor.update(tObj);
        } else { // key not exist
            objectStore.add(tObj);
        }
    };
    request.onerror = this.error;
}

/**
 * Retrieves an object team from the indexedDB.
 * @param {int} id
 * @param {function} callback
 * @return {Team} teamObject
 */
Database.prototype.getTeam = function(id, callback){
    var	transaction = this.request.result.transaction(["teams"], "readwrite");
    var	objectStore = transaction.objectStore("teams");
    var request = objectStore.get(id);
    var dbObject = this;

    request.onsuccess = function(){
        var team = new Team();
        team.convertToBusinessObject(request.result);
        callback(team);
    };
    request.onerror = this.error;
}

/**
 * Calls the callbackfunction with a Matchobject as the first param
 * @param {int} id
 * @param {function} callback
 */
Database.prototype.getMatchById = function(id, callback){
    var	transaction = this.request.result.transaction(["matches"], "readwrite");
    var	objectStore = transaction.objectStore("matches");
    var request = objectStore.get(id);
    var dbObject = this;

    request.onsuccess = function(){
        var match = new Match();
        match.convertToBusinessObject(request.result);
        dbObject.getGoalsByMatchId(match.getId(), function(arrGoals){
            for(var key in arrGoals){
                match.addGoal(arrGoals[key]);
            }
            callback(match);
        });
    };
    request.onerror = this.error;
}